﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;

namespace LookUpLater
{
    public class Category : IDisposable
    {
        public string Name { get; set; }
        public List<Type> Types { get; set; }
        public Category(List<Type> types)
        {
            this.Types = types;
        }
        private Category()
        {
            LoadXml();
        }

        private void LoadXml()
        {
            var xmlPath = Path.Combine(Directory.GetCurrentDirectory(), "Category.xml");
            var rootNode = XDocument.Load(xmlPath).Element("Category");
            //this.Name = rootNode.Attribute("name").Value;
            this.Types = rootNode.Elements("Type").Select(t => new Type(t)).ToList();
        }

        public static Category Refresh()
        {
            currentCategory = new Category();
            return currentCategory;
        }

        private static Category currentCategory;
        public static Category CurrentCategory
        {
            get
            {
                if (currentCategory == null)
                    currentCategory = new Category();
                return currentCategory;
            }
        }

        public void Dispose()
        {
            currentCategory = null;
        }

        public bool Save()
        {
            try
            {
                var types = AddorUpdate();
                if (types != null)
                {
                    var xmls = types.Select(t => t.ToXml());
                    var xmlPath = Path.Combine(Directory.GetCurrentDirectory(), "Category.xml");
                    var rootDoc = XDocument.Load(xmlPath);
                    rootDoc.Element("Category").RemoveAll();
                    rootDoc.Element("Category").Add(xmls);
                    rootDoc.Save(xmlPath);
                    currentCategory = Refresh();
                }
                return true;
            }
            catch
            {
                return false;
            }
        }
        private List<Type> AddorUpdate()
        {
            var category = new Category();
            var typeExists = category.Types.Any(t => t.Name.Equals(this.Types.First().Name));
            if (!typeExists)
                category.Types.Add(this.Types.First());
            
            var selectedType = category.Types.First(t => t.Name.Equals(this.Types.First().Name));

            if (selectedType.SubCategories == null)
                selectedType.SubCategories = new List<SubCategory>();
            
            var subcatexists = selectedType.SubCategories.Any(s => s.Name.Equals(this.Types.First().SubCategories.First().Name));
            if (!subcatexists)
                selectedType.SubCategories.Add(this.Types.First().SubCategories.First());

            var selectedSubtype=selectedType.SubCategories.First(s=>s.Name.Equals(this.Types.First().SubCategories.First().Name));
            if (selectedSubtype.Groups == null)
                selectedSubtype.Groups = new List<Group>();
            
            var groupexists = selectedSubtype.Groups.Any(c => c.Name.Equals(this.Types.First().SubCategories.First().Groups.First().Name));
            if (!groupexists)
                selectedSubtype.Groups.Add(this.Types.First().SubCategories.First().Groups.First());
            if (typeExists && subcatexists && groupexists)
                return null;
            return category.Types;
        }
    }

    /// <summary>
    /// Type
    /// </summary>
    public class Type
    {
        public Type(string name, List<SubCategory> subcategories = null)
        {
            this.Name = name;
            this.SubCategories = subcategories;
        }
        public Type(XElement element)
        {
            this.Name = element.Attribute("name").Value;
            this.SubCategories = element.Elements("SubCategory").Select(s => new SubCategory(s)).ToList();
        }
        public string Name { get; set; }
        public List<SubCategory> SubCategories { get; set; }
        public XElement ToXml()
        {
            return new XElement("Type", new XAttribute("name", this.Name), this.SubCategories.Select(s => s.ToXml()));
        }
    }

    /// <summary>
    /// SubCategory
    /// </summary>
    public class SubCategory
    {
        public SubCategory(string name, List<Group> groups = null)
        {
            this.Name = name;
            this.Groups = groups;
        }
        public SubCategory(XElement element)
        {
            this.Name = element.Attribute("name").Value;
            this.Groups = element.Elements("Group").Select(s => new Group(s)).ToList();
        }
        public string Name { get; set; }
        public List<Group> Groups { get; set; }
        public XElement ToXml()
        {
            return new XElement("SubCategory", new XAttribute("name", this.Name), this.Groups.Select(g => g.ToXml()));
        }
    }

    /// <summary>
    /// Group
    /// </summary>
    public class Group
    {
        public Group(string name)
        {
            this.Name = name;
        }
        public Group(XElement element)
        {
            this.Name = element.Attribute("name").Value;
        }
        public string Name { get; set; }
        public XElement ToXml()
        {
            return new XElement("Group", new XAttribute("name", this.Name));
        }
    }
}
